/*******************************************************************************
 * Copyright (c) 2002 Boris Pruessmann and others. All rights reserved. This
 * program and the accompanying materials are made available under the terms of
 * the Common Public License v0.5 which accompanies this distribution, and is
 * available at http://www.eclipse.org/legal/cpl-v05.html
 * 
 * Contributors: Boris Pruessmann - Initial implementation.
 ******************************************************************************/
package net.sourceforge.perforce.ui.views;

import java.util.ArrayList;
import java.util.List;

import net.sourceforge.perforce.core.resources.IP4File;
import net.sourceforge.perforce.core.syncinfo.ResourceSyncInfo;
import net.sourceforge.perforce.ui.OverlayIcon;
import net.sourceforge.perforce.ui.OverlayIconCache;

import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.ILabelDecorator;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.Point;

/**
 * @version $Revision: 488 $
 * @author <a href="mailto:bpruessmann@users.sourceforge.net">Boris
 *         Pruessmann</a>
 */
public class ChangelistViewDecorator extends LabelProvider implements ILabelDecorator {
  // ---------------------------------------------------------------------------
  // Private Variables

  /** The OverlayIconCache. */
  private OverlayIconCache iconCache = new OverlayIconCache();

  // ------------------------------------------------------------ Public Methods
  // (ILabelDecorator)

  /** @see ILabelDecorator#decorateImage(Image, Object) */
  public Image decorateImage(Image image, Object element) {
    if (!(element instanceof IP4File)) {
      return image;
    }

    IP4File file = (IP4File) element;
    DecoratorOverlayIcon decoratedImage = decorateImage(image, file);
    if (decoratedImage == null) {
      return image;
    }

    return iconCache.getImageFor(decoratedImage);
  }

  /** @see ILabelDecorator#decorateText(String, Object) */
  public String decorateText(String text, Object element) {
    return text;
  }

  // --------------------------------------------------------- Public Methods
  // (IBaseLabelProvider)

  @Override
  public void dispose() {
    iconCache.disposeAll();
  }

  //----------------------------------------------------------------------------
  // - Private Methods

  /**
   * Called to calculate the DecoratorOverlayIcon for the given IP4File.
   * 
   * @param image the image to decorate.
   * @param file the file.
   * @return the decoration.
   */
  private DecoratorOverlayIcon decorateImage(Image image, IP4File file) {
    List<ImageDescriptor> overlays = new ArrayList<ImageDescriptor>();
    List<Integer> locations = new ArrayList<Integer>();

    boolean ourFile = file.getClientName().equals(file.getServer().getClient());

    if (file.getAction().equals(ResourceSyncInfo.ACTION_ADD)) {
      if (ourFile) {
        overlays.add(OverlayIconCache.OPEN_FOR_ADD);
        locations.add(Integer.valueOf(OverlayIconCache.OPEN_FOR_ADD_LOCATION));
      } else {
        overlays.add(OverlayIconCache.OTHER_OPEN_FOR_ADD);
        locations.add(Integer.valueOf(OverlayIconCache.OTHER_OPEN_FOR_ADD_LOCATION));
      }
    }
    if (file.getAction().equals(ResourceSyncInfo.ACTION_BRANCH)) {
      if (ourFile) {
        overlays.add(OverlayIconCache.OPEN_FOR_ADD);
        locations.add(Integer.valueOf(OverlayIconCache.OPEN_FOR_ADD_LOCATION));
      } else {
        overlays.add(OverlayIconCache.OTHER_OPEN_FOR_ADD);
        locations.add(Integer.valueOf(OverlayIconCache.OTHER_OPEN_FOR_ADD_LOCATION));
      }
    } else if (file.getAction().equals(ResourceSyncInfo.ACTION_DELETE)) {
      if (ourFile) {
        overlays.add(OverlayIconCache.OPEN_FOR_DELETE);
        locations.add(Integer.valueOf(OverlayIconCache.OPEN_FOR_DELETE_LOCATION));
      } else {
        overlays.add(OverlayIconCache.OTHER_OPEN_FOR_DELETE);
        locations.add(Integer.valueOf(OverlayIconCache.OTHER_OPEN_FOR_DELETE_LOCATION));
      }
    } else if (file.getAction().equals(ResourceSyncInfo.ACTION_EDIT)) {
      if (ourFile) {
        overlays.add(OverlayIconCache.OPEN_FOR_EDIT);
        locations.add(Integer.valueOf(OverlayIconCache.OPEN_FOR_EDIT_LOCATION));
      } else {
        overlays.add(OverlayIconCache.OTHER_OPEN_FOR_EDIT);
        locations.add(Integer.valueOf(OverlayIconCache.OTHER_OPEN_FOR_EDIT_LOCATION));
      }
    }

    if (file.needsResolve()) {
      overlays.add(OverlayIconCache.OUT_OF_DATE);
      locations.add(Integer.valueOf(OverlayIconCache.OUT_OF_DATE_LOCATION));
    }

    if (file.hasOurLock()) {
      overlays.add(OverlayIconCache.OUR_LOCK);
      locations.add(Integer.valueOf(OverlayIconCache.OUR_LOCK_LOCATION));
    }

    if (overlays.isEmpty()) {
      return null;
    } else {
      Integer[] integers = locations.toArray(new Integer[locations.size()]);
      int[] ints = new int[integers.length];
      for (int i = 0; i < integers.length; i++) {
        ints[i] = integers[i].intValue();
      }

      ImageDescriptor[] imageDescriptors = overlays.toArray(new ImageDescriptor[overlays.size()]);
      return new DecoratorOverlayIcon(image, imageDescriptors, ints);
    }
  }

  // ----------------------------------------------------------------------
  // Private Nested Classes

  /** The decorator's OverlayIcon. */
  private static class DecoratorOverlayIcon extends OverlayIcon {
    // ---------------------------------------------------------------------
    // Public Constructors

    /**
     * Constructor for DecoratorOverlayIcon.
     * 
     * @param base the base iamge.
     * @param overlays the overlay to apply.
     * @param locations the locations of the overlays.
     */
    public DecoratorOverlayIcon(Image base, ImageDescriptor[] overlays, int[] locations) {
      super(base, overlays, locations, new Point(base.getBounds().width, base.getBounds().height));
    }

    // -----------------------------------------------------------------------
    // Protected Methods

    @Override
    protected void drawOverlays(ImageDescriptor[] overlays, int[] locations) {
      Point size = getSize();
      for (int i = overlays.length - 1; i >= 0; --i) {
        ImageData imageData = overlays[i].getImageData();

        switch (locations[i]) {
          case TOP_LEFT:
            drawImage(imageData, 0, 0);
            break;

          case TOP_RIGHT:
            drawImage(imageData, size.x - imageData.width, 0);
            break;

          case BOTTOM_LEFT:
            drawImage(imageData, 0, size.y - imageData.height);
            break;

          case BOTTOM_RIGHT:
            drawImage(imageData, size.x - imageData.width, size.y - imageData.height);
            break;
        }
      }
    }
  }
}
